﻿Imports System.IO
Imports System.Text
Imports System.Threading
Imports System.Xml

Public Class frmMain

    ' Declare a cancellation token that will be used to cancel async tasks
    Protected Friend cts As CancellationTokenSource
    ' Declare a pause token that will be used to pause async tasks
    Protected Friend pts As PauseTokenSource

#Region "Custom methods"

    ''' <summary>
    ''' Cleaner core refatored code
    ''' </summary>
    ''' <remarks></remarks>
    Private Async Function RunCleaner() As Task
        ' Create a new StringBuilder which will be used to hold the path of the folders that couldn't be deleted
        Dim exceptionList As New StringBuilder()

        ' Initialize the cancellation token source and retrieve the token
        cts = New CancellationTokenSource()
        Dim token As CancellationToken = cts.Token

        ' Initialize the pause token source and retrieve the token
        pts = New PauseTokenSource()
        Dim pauseToken As PauseToken = pts.Token

        ' Create two Long values that will hold the total size of files and folders to be deleted and the actual size
        Dim totalSize, actualSize As Long

        Try
            ' If required, re-calculate folders sizes
            If Not AppSettings.ErrorDetected AndAlso AppSettings.RefreshSizeBeforeRunningCleaner Then
                Await RefreshFolderSizes(False, token, pauseToken)
            End If

            ' Perform preparing operations
            ' Show progress bar and set its properties
            If Not tSProgressBar.Visible Then
                tSProgressBar.Visible = True
            End If
            tSProgressBar.Value = 0
            tSProgressBar.Maximum = mainListView.Items.Count

            ' Show and enable cancel button
            cancelLinkLabel.Visible = True
            cancelLinkLabel.Enabled = True

            ' Count the total size of files and folders to be deleted
            totalSize = Await GetItemsSize(token, pauseToken)

            Await Task.Run(Async Function()
                               For Each item As ListViewItem In mainListView.CheckedItems
                                   ' Throw the cancellation request if the token has one
                                   token.ThrowIfCancellationRequested()
                                   Await pauseToken.WaitWhilePausedAsync()

                                   If item.Group IsNot mainListView.Groups("Custom") Then
                                       ' Set ToolStripStatusLabel text to the file or folder being processed
                                       tSStatusLabel.Text = "Deleting: " & Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                                                "\Packages\" & item.Group.Header & "\" & item.Text

                                       ' Run the cleaner. Retrieve the exception list
                                       exceptionList = Await ClearFolderContent(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                                                "\Packages\" & item.Group.Header & "\" & item.Text, exceptionList, token, pauseToken)

                                       ' Re-calculate folder size
                                       item.SubItems(1).Text = _
                                           Await GetFolderSize(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                                               "\Packages\" & item.Group.Header & "\" & item.Text, token)
                                   Else
                                       ' Set ToolStripStatusLabel text to the file or folder being processed
                                       tSStatusLabel.Text = "Deleting: " & item.Text

                                       ' Run the cleaner. Retrieve the exception list
                                       exceptionList = Await ClearFolderContent(item.Text, exceptionList, token, pauseToken)

                                       ' Re-calculate folder size
                                       item.SubItems(1).Text = Await GetFolderSize(item.Text, token)
                                   End If

                                   ' Increment progress bar value
                                   tSProgressBar.Increment(1)
                               Next
                           End Function, token)

            ' Get the actual size
            actualSize = Await GetItemsSize(token, pauseToken)
        Catch oc As OperationCanceledException
            exceptionList.AppendLine()
            exceptionList.AppendLine("NOTE: Task was cancelled")
        End Try

        ' Perform form cleanup operations
        ' Clear the cancellation token
        cts.Dispose()
        pts = Nothing

        ' Get the total space freed as string (like the mainListView items size)
        Dim spaceFreed As String = Await GetSizeMultiplier(totalSize - actualSize)

        ' Hide and disable cancel button
        cancelLinkLabel.Visible = False
        cancelLinkLabel.Enabled = False

        ' Reset the ToolStripStatusLabel text and hide the progress bar
        tSStatusLabel.Text = "Ready"
        If tSProgressBar.Visible Then
            tSProgressBar.Visible = False
        End If
        ' Reset the RunCleaner button's text
        runCleanerButton.Text = "Run Cleaner"

        ' Show a MessageBox containing the files or folders that couldn't be deleted if there were any
        If exceptionList.ToString IsNot String.Empty Then
            ' Sound a beep
            Beep()

            ' Initialize a new istance of the cleanup confirmation form
            Using cleanupForm As New frmCleanupComplete()
                cleanupForm.cleanupDetailsLabel.Text = "Total space freed: " & spaceFreed + ControlChars.CrLf + ControlChars.CrLf + "Some file or folder couldn't be deleted: " & exceptionList.ToString
                cleanupForm.ShowDialog()
            End Using
        Else
            ' Sound a beep
            Beep()

            ' Initialize a new istance of the cleanup confirmation form
            Using cleanupForm As New frmCleanupComplete()
                cleanupForm.cleanupDetailsLabel.Text = "Total space freed: " & spaceFreed
                cleanupForm.ShowDialog()
            End Using
        End If

        ' Clear the StringBuilder
        If exceptionList IsNot Nothing Then
            exceptionList.Clear()
        End If
    End Function

    ''' <summary>
    ''' Remove folder core refactored code
    ''' </summary>
    ''' <remarks></remarks>
    Private Async Function RemoveFolder() As Task
        ' Perform preparing operations
        ' Show progress bar and set its properties
        If Not tSProgressBar.Visible Then
            tSProgressBar.Visible = True
        End If
        tSProgressBar.Value = 0
        tSProgressBar.Maximum = mainListView.SelectedItems.Count

        ' Show and enable cancel button
        cancelLinkLabel.Visible = True
        cancelLinkLabel.Enabled = True

        ' Initialize the cancellation token source and retrieve the token
        cts = New CancellationTokenSource()
        Dim token As CancellationToken = cts.Token

        Try
            ' Check if the number of selected items is bigger than 0
            If mainListView.SelectedItems.Count >= 1 Then
                ' Iterate through all the selected items and remove them.
                Await Task.Run(Sub()
                                   For Each item As ListViewItem In mainListView.SelectedItems
                                       If token.IsCancellationRequested Then
                                           ' Clean up here

                                           ' Throw the cancellation request
                                           token.ThrowIfCancellationRequested()
                                       End If

                                       ' Set ToolStripStatusLabel text to the file or folder being processed
                                       tSStatusLabel.Text = "Removing: " & Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                                                "\Packages\" & item.Group.Header & "\" & item.Text
                                       item.Remove()

                                       ' Increment progress bar value
                                       tSProgressBar.Increment(1)
                                   Next
                               End Sub, token)
            ElseIf mainListView.SelectedItems.Count = 0 Then
                ' If there's no selected item, disable the "Remove" button and show a warning message
                removeFolderButton.Enabled = False
                MessageBox.Show("No items selected", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            End If
        Catch oc As OperationCanceledException
        End Try

        ' Perform form cleanup operations
        ' Clear the cancellation token
        cts.Dispose()

        ' Hide and disable cancel button
        cancelLinkLabel.Visible = False
        cancelLinkLabel.Enabled = False

        ' Enable or disable the 'Run Cleaner'
        ActivateButtons()

        ' Reset the ToolStripStatusLabel text and hide the progress bar
        tSStatusLabel.Text = "Ready"
        If tSProgressBar.Visible Then
            tSProgressBar.Visible = False
        End If
    End Function

    ''' <summary>
    ''' Refresh folders sizes core refactored code
    ''' </summary>
    ''' <param name="cleanup">Indicate if we should perform the form cleanup, such as hiding progress bar etc.</param>
    ''' <param name="token">The cancellation token</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Async Function RefreshFolderSizes(cleanup As Boolean, token As CancellationToken, pauseToken As PauseToken) As Task
        ' Perform preparing operations
        ' Show the progress bar and reset its value
        If Not tSProgressBar.Visible Then
            tSProgressBar.Visible = True
        End If
        tSProgressBar.Value = 0

        ' Show and enable cancel button
        cancelLinkLabel.Visible = True
        cancelLinkLabel.Enabled = True

        ' Set the progress bar maximum value, so we can track progress      
        tSProgressBar.Maximum = mainListView.Items.Count

        Dim totalSize As Long = 0

        ' Process folders
        Try
            Await Task.Run(Async Function()
                               For Each item As ListViewItem In mainListView.Items
                                   token.ThrowIfCancellationRequested()
                                   Await pauseToken.WaitWhilePausedAsync()

                                   If item.Group IsNot mainListView.Groups("Custom") Then
                                       ' Set ToolStripStatusLabel text to the file or folder being processed
                                       tSStatusLabel.Text = "Calculating: " & Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                                                "\Packages\" & item.Group.Header & "\" & item.Text

                                       ' Calculate folder size
                                       'item.SubItems(1).Text = _
                                       '    Await GetFolderSize(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                       '                        "\Packages\" & item.Group.Header & "\" & item.Text, token)
                                       Dim size As Long = Await GetFolderSize(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                                                              "\Packages\" & item.Group.Header & "\" & item.Text, token)
                                       totalSize += size
                                       item.SubItems(1).Text = Await GetSizeMultiplier(size)
                                   Else
                                       ' Set ToolStripStatusLabel text to the file or folder being processed
                                       tSStatusLabel.Text = "Calculating: " & item.Text

                                       ' Calculate folder size
                                       'item.SubItems(1).Text = Await GetFolderSize(item.Text, token)
                                       Dim size As Long = Await GetFolderSize(item.Text, token)
                                       totalSize += size
                                       item.SubItems(1).Text = Await GetSizeMultiplier(size)
                                   End If

                                   ' Increment progress bar value
                                   tSProgressBar.Increment(1)
                               Next

                               tSStatusLabel.Text = "Ready | " + Await GetSizeMultiplier(totalSize) + " to clean"
                           End Function, token)
        Catch oc As OperationCanceledException
        End Try

        ' Perform form cleanup operations
        If cleanup Then
            ' Hide and disable cancel button
            cancelLinkLabel.Visible = False
            cancelLinkLabel.Enabled = False

            ' Reset the ToolStripStatusLabel text and hide the progress bar
            If tSProgressBar.Visible Then
                tSProgressBar.Visible = False
            End If
        End If
    End Function

    ''' <summary>
    ''' Asyncronously create the XML settings file
    ''' </summary>
    ''' <remarks></remarks>
    Private Async Function CreateXMLSettingsFile() As Task
        If Not My.Computer.FileSystem.DirectoryExists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                         "\Modern UI Apps Cleaner") Then
            My.Computer.FileSystem.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                         "\Modern UI Apps Cleaner")
        End If

        Await Task.Run(Sub()
                           Using writer As XmlWriter = XmlWriter.Create(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                     "\Modern UI Apps Cleaner\config.dat", New XmlWriterSettings With {.Indent = True})
                               writer.WriteStartDocument()
                               writer.WriteComment("DO NOT MODIFY THIS FILE." + ControlChars.CrLf + _
                                                   "ANY CHANGE MADE CAN MAKE THE APPLICATION TO NOT WORK PROPERLY.")
                               writer.WriteStartElement("Configuration")
                               writer.WriteElementString("ScanInstalledAppsAtStartup", "True")
                               writer.WriteElementString("OverwriteMethod", "0")
                               writer.WriteElementString("OverwriteType", "1")
                               writer.WriteElementString("ConfirmWhenDeletingFolder", "False")
                               writer.WriteElementString("ConfirmBeforeRunningCleaner", "False")
                               writer.WriteElementString("RefreshSizeBeforeRunningCleaner", "True")
                               writer.WriteEndElement()
                               writer.WriteEndDocument()

                               writer.Close()
                           End Using

                           ' Create a backup copy of the settings file
                           My.Computer.FileSystem.CopyFile(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                           "\Modern UI Apps Cleaner\config.dat", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                           "\Modern UI Apps Cleaner\config.bak", True)
                       End Sub)
    End Function

    ''' <summary>
    ''' Enable or disable the 'Run Cleaner' button, 'Run Cleaner' ToolStripMenuItem
    ''' 'Refresh folders sizes' ToolStripMenuItem and 'Select All' ToolStripMenuItem
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub ActivateButtons()
        ' If there's any item, enable it. Otherwise, disable it.
        If mainListView.Items.Count > 0 Then
            runCleanerButton.Enabled = True
            RunCleanerToolStripMenuItem.Enabled = True
            RefreshFoldersSizesToolStripMenuItem.Enabled = True
            SelectAllToolStripMenuItem.Enabled = True
        Else
            runCleanerButton.Enabled = False
            RunCleanerToolStripMenuItem.Enabled = False
            RefreshFoldersSizesToolStripMenuItem.Enabled = False
            SelectAllToolStripMenuItem.Enabled = False
        End If
    End Sub

    ''' <summary>
    ''' Get the sum of the sizes hold in the mainListView items 
    ''' </summary>
    ''' <returns>The total size as Long</returns>
    ''' <remarks></remarks>
    Private Async Function GetItemsSize(token As CancellationToken, pauseToken As PauseToken) As Task(Of Long)
        ' Initialize a long that will hold the size
        Dim finalSize As Long = 0

        ' Iterate through the ListView items
        Await Task.Run(Async Function()
                           For Each item As ListViewItem In mainListView.Items
                               ' Throw the cancellation request if the token has one
                               token.ThrowIfCancellationRequested()
                               Await pauseToken.WaitWhilePausedAsync()

                               finalSize += Await GetOriginalSize(item.SubItems(1).Text)
                           Next
                       End Function, token)

        Return finalSize
    End Function

    ''' <summary>
    ''' Clear the ListView groups except the group named "Custom"
    ''' </summary>
    ''' <remarks><see cref="addFolderButton_Click"></see></remarks>
    Private Sub ClearListViewGroups()
        ' Clear the ListView groups, except the 'Custom' group
        If mainListView.Groups("Custom") Is Nothing Then
            mainListView.Groups.Clear()
        Else
            ' Clone the 'Custom' group
            Dim customGroup As ListViewGroup = mainListView.Groups.Item("Custom")

            ' Clear the ListView
            mainListView.Groups.Clear()

            ' Re-add the 'Custom' group
            mainListView.Groups.Add(customGroup)
        End If
    End Sub

    ''' <summary>
    ''' Asyncronously scan for folders that contains temporary files in a given folder that belongs to %LOCALAPPDATA%\Packages
    ''' </summary>
    ''' <param name="folder">The folder to be analyzed</param>
    ''' <param name="group">The ListViewGroup that will hold the items created from the folders found</param>
    ''' <remarks></remarks>
    Private Async Function ProcessFolders(folder As DirectoryInfo, group As ListViewGroup, token As CancellationToken) As Task
        ' Process the INetCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\AC\INetCache") Then
            ' Create a new ListViewItem, add it a sub item that will show the folder size
            ' and add the item to the ListView
            Dim inetcacheItem As New ListViewItem("AC\INetCache")
            inetcacheItem.Checked = True
            inetcacheItem.Group = group
            inetcacheItem.ToolTipText = folder.FullName & "\" & inetcacheItem.Text
            inetcacheItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\AC\INetCache", token))

            mainListView.Items.Add(inetcacheItem)
        End If
        ' End INetCache

        ' Process the INetCookies folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\AC\INetCookies") Then
            ' Same as for the INetCache folder
            Dim inetcookiesItem As New ListViewItem("AC\INetCookies")
            inetcookiesItem.Checked = True
            inetcookiesItem.Group = group
            inetcookiesItem.ToolTipText = folder.FullName & "\" & inetcookiesItem.Text
            inetcookiesItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\AC\INetCookies", token))

            mainListView.Items.Add(inetcookiesItem)
        End If
        ' End INetCookies

        ' Process the INetHistory folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\AC\INetHistory") Then
            ' Same as for the INetCache and INetCookies folders
            Dim inethistoryItem As New ListViewItem("AC\INetHistory")
            inethistoryItem.Checked = True
            inethistoryItem.Group = group
            inethistoryItem.ToolTipText = folder.FullName & "\" & inethistoryItem.Text
            inethistoryItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\AC\INetHistory", token))

            mainListView.Items.Add(inethistoryItem)
        End If
        ' End INetHistory

        ' Process the AC\Microsoft\CryptnetUrlCache\MetaData folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\AC\Microsoft\CryptnetUrlCache\MetaData") Then
            ' Same as for the INetCache and INetCookies folders
            Dim acCryptMetaItem As New ListViewItem("AC\Microsoft\CryptnetUrlCache\MetaData")
            acCryptMetaItem.Checked = True
            acCryptMetaItem.Group = group
            acCryptMetaItem.ToolTipText = folder.FullName & "\" & acCryptMetaItem.Text
            acCryptMetaItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\AC\Microsoft\CryptnetUrlCache\MetaData", token))

            mainListView.Items.Add(acCryptMetaItem)
        End If
        ' End AC\Microsoft\CryptnetUrlCache\MetaData

        ' Process the AC\Temp folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\AC\Temp") Then
            ' Same as for the INetCache and INetCookies folders
            Dim acTempItem As New ListViewItem("AC\Temp")
            acTempItem.Checked = True
            acTempItem.Group = group
            acTempItem.ToolTipText = folder.FullName & "\" & acTempItem.Text
            acTempItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\AC\Temp", token))

            mainListView.Items.Add(acTempItem)
        End If
        ' End Temp

        ' Process cacheBingDailyClusterDefinitionsCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheBingDailyClusterDefinitionsCache") Then
            ' Same as for the INetCache and INetCookies folders
            Dim cacheBingDailyClusterDefinitionsCacheItem As New ListViewItem("LocalState\Cache\cacheBingDailyClusterDefinitionsCache")
            cacheBingDailyClusterDefinitionsCacheItem.Checked = True
            cacheBingDailyClusterDefinitionsCacheItem.Group = group
            cacheBingDailyClusterDefinitionsCacheItem.ToolTipText = folder.FullName & "\" & cacheBingDailyClusterDefinitionsCacheItem.Text
            cacheBingDailyClusterDefinitionsCacheItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheBingDailyClusterDefinitionsCache", token))

            mainListView.Items.Add(cacheBingDailyClusterDefinitionsCacheItem)
        End If
        ' End cacheBingDailyClusterDefinitionsCache folder

        ' Process cacheArticles folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheArticles") Then
            ' Same as for the INetCache and INetCookies folders
            Dim cacheArticlesItem As New ListViewItem("LocalState\Cache\cacheArticles")
            cacheArticlesItem.Checked = True
            cacheArticlesItem.Group = group
            cacheArticlesItem.ToolTipText = folder.FullName & "\" & cacheArticlesItem.Text
            cacheArticlesItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheArticles", token))

            mainListView.Items.Add(cacheArticlesItem)
        End If
        ' End cacheArticles folder

        ' Process cacheBingNews folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheBingNews") Then
            ' Same as for the INetCache and INetCookies folders
            Dim cacheBingNewsItem As New ListViewItem("LocalState\Cache\cacheBingNews")
            cacheBingNewsItem.Checked = True
            cacheBingNewsItem.Group = group
            cacheBingNewsItem.ToolTipText = folder.FullName & "\" & cacheBingNewsItem.Text
            cacheBingNewsItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheBingNews", token))

            mainListView.Items.Add(cacheBingNewsItem)
        End If
        ' End cacheBingNews folder

        ' Process cacheConfigurationCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheConfigurationCache") Then
            ' Same as for the INetCache and INetCookies folders
            Dim configCacheItem As New ListViewItem("LocalState\Cache\cacheConfigurationCache")
            configCacheItem.Checked = True
            configCacheItem.Group = group
            configCacheItem.ToolTipText = folder.FullName & "\" & configCacheItem.Text
            configCacheItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheConfigurationCache", token))

            mainListView.Items.Add(configCacheItem)
        End If
        ' End cacheConfigurationCache folder

        ' Process cacheEditorial folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheEditorial") Then
            ' Same as for the INetCache and INetCookies folders
            Dim cacheEditorialItem As New ListViewItem("LocalState\Cache\cacheEditorial")
            cacheEditorialItem.Checked = True
            cacheEditorialItem.Group = group
            cacheEditorialItem.ToolTipText = folder.FullName & "\" & cacheEditorialItem.Text
            cacheEditorialItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheEditorial", token))

            mainListView.Items.Add(cacheEditorialItem)
        End If
        ' End cacheEditorial folder

        ' Process cacheInfoCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheInfoCache") Then
            ' Same as for the INetCache and INetCookies folders
            Dim cacheInfoItem As New ListViewItem("LocalState\Cache\cacheInfoCache")
            cacheInfoItem.Checked = True
            cacheInfoItem.Group = group
            cacheInfoItem.ToolTipText = folder.FullName & "\" & cacheInfoItem.Text
            cacheInfoItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheInfoCache", token))

            mainListView.Items.Add(cacheInfoItem)
        End If
        ' End cacheInfoCache folder

        ' Process cacheMinuteCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheMinuteCache") Then
            ' Same as for the INetCache and INetCookies folders
            Dim cacheMinuteItem As New ListViewItem("LocalState\Cache\cacheMinuteCache")
            cacheMinuteItem.Checked = True
            cacheMinuteItem.Group = group
            cacheMinuteItem.ToolTipText = folder.FullName & "\" & cacheMinuteItem.Text
            cacheMinuteItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheMinuteCache", token))

            mainListView.Items.Add(cacheMinuteItem)
        End If
        ' End cacheMinuteCache folder

        ' Process cachePlatformImageCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cachePlatformImageCache") Then
            ' Same as for the INetCache and INetCookies folders
            Dim platformImageCacheItem As New ListViewItem("LocalState\Cache\cachePlatformImageCache")
            platformImageCacheItem.Checked = True
            platformImageCacheItem.Group = group
            platformImageCacheItem.ToolTipText = folder.FullName & "\" & platformImageCacheItem.Text
            platformImageCacheItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cachePlatformImageCache", token))

            mainListView.Items.Add(platformImageCacheItem)
        End If
        ' End cachePlatformImageCache folder

        ' Process cachePlatformTopEdgyImageCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cachePlatformTopEdgyImageCache") Then
            ' Same as for the INetCache and INetCookies folders
            Dim platformTopEdgyImageCacheItem As New ListViewItem("LocalState\Cache\cachePlatformTopEdgyImageCache")
            platformTopEdgyImageCacheItem.Checked = True
            platformTopEdgyImageCacheItem.Group = group
            platformTopEdgyImageCacheItem.ToolTipText = folder.FullName & "\" & platformTopEdgyImageCacheItem.Text
            platformTopEdgyImageCacheItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cachePlatformTopEdgyImageCache", token))

            mainListView.Items.Add(platformTopEdgyImageCacheItem)
        End If
        ' End cachePlatformTopEdgyImageCache folder

        ' Process cacheSportsHeroImageCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheSportsHeroImageCache") Then
            ' Same as for the INetCache and INetCookies folders
            Dim cacheSportsHeroImageCacheItem As New ListViewItem("LocalState\Cache\cacheSportsHeroImageCache")
            cacheSportsHeroImageCacheItem.Checked = True
            cacheSportsHeroImageCacheItem.Group = group
            cacheSportsHeroImageCacheItem.ToolTipText = folder.FullName & "\" & cacheSportsHeroImageCacheItem.Text
            cacheSportsHeroImageCacheItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheSportsHeroImageCache", token))

            mainListView.Items.Add(cacheSportsHeroImageCacheItem)
        End If
        ' End cacheSportsHeroImageCache folder

        ' Process cacheSportsHeroImageCache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\cacheSearchGrammarCache") Then
            ' Same as for the INetCache and INetCookies folders
            Dim cacheSearchGrammarCacheItem As New ListViewItem("LocalState\Cache\cacheSearchGrammarCache")
            cacheSearchGrammarCacheItem.Checked = True
            cacheSearchGrammarCacheItem.Group = group
            cacheSearchGrammarCacheItem.ToolTipText = folder.FullName & "\" & cacheSearchGrammarCacheItem.Text
            cacheSearchGrammarCacheItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\cacheSearchGrammarCache", token))

            mainListView.Items.Add(cacheSearchGrammarCacheItem)
        End If
        ' End cacheSportsHeroImageCache folder

        ' Process ImageCache\20 folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\ImageCache\20") Then
            ' Same as for the INetCache and INetCookies folders
            Dim image20Item As New ListViewItem("LocalState\ImageCache\20")
            image20Item.Checked = True
            image20Item.Group = group
            image20Item.ToolTipText = folder.FullName & "\" & image20Item.Text
            image20Item.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\ImageCache\20", token))

            mainListView.Items.Add(image20Item)
        End If
        ' End ImageCache\20 folder

        ' Process SugarSync.SugarSync_czjgh7s87r8wg\LocalState\Cache folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache") AndAlso folder.Name.Contains("SugarSync") Then
            ' Same as for the INetCache and INetCookies folders
            Dim sugarSyncCacheItem As New ListViewItem("LocalState\Cache")
            sugarSyncCacheItem.Checked = True
            sugarSyncCacheItem.Group = group
            sugarSyncCacheItem.ToolTipText = folder.FullName & "\" & sugarSyncCacheItem.Text
            sugarSyncCacheItem.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache", token))

            mainListView.Items.Add(sugarSyncCacheItem)
        End If
        ' End SugarSync.SugarSync_czjgh7s87r8wg\LocalState\Cache folder

        ' Process Microsoft.BingNews_8wekyb3d8bbwe\LocalState\Cache\Images folder
        If My.Computer.FileSystem.DirectoryExists(folder.FullName & "\LocalState\Cache\Images") AndAlso folder.Name.Contains("BingNews") Then
            ' Same as for the INetCache and INetCookies folders
            Dim newsImages As New ListViewItem("LocalState\Cache")
            newsImages.Checked = True
            newsImages.Group = group
            newsImages.ToolTipText = folder.FullName & "\" & newsImages.Text
            newsImages.SubItems.Add(Await GetFolderSize(folder.FullName & "\LocalState\Cache\Images", token))

            mainListView.Items.Add(newsImages)
        End If
        ' End Microsoft.BingNews_8wekyb3d8bbwe\LocalState\Cache\Images folder

        ' Throw the cancellation request if the token has one
        token.ThrowIfCancellationRequested()
    End Function
#End Region

    Private Async Sub frmMain_Load(sender As Object, e As EventArgs) Handles Me.Load
        ' Create the settings directory if it doesn't exist
        If Not My.Computer.FileSystem.DirectoryExists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                      "\Modern UI Apps Cleaner") Then
            My.Computer.FileSystem.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                   "\Modern UI Apps Cleaner")
        End If

        ' Create the XML settings file if it doesn't exist or is not a valid XML settings file
        If Not My.Computer.FileSystem.FileExists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                 "\Modern UI Apps Cleaner\config.dat") Then
            Await CreateXMLSettingsFile()
        Else
            If Not Await CheckIfValidSettings() Then
                Await CreateXMLSettingsFile()
            End If
        End If

        ' Disable the app scanner feature if OS isn't Windows 8 or Windows 8.1
        If Not My.Computer.Info.OSFullName.Contains("Windows 8") Or _
            Not My.Computer.Info.OSFullName.Contains("Windows 8.1") Then

            scanInstalledAppsButton.Enabled = False
        End If

        ' Enable or disable the 'Run Cleaner'
        ActivateButtons()
    End Sub

    Private Sub frmMain_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        ' Check if running OS is Windows 8 or 8.1
        Dim ci As New Devices.ComputerInfo()
        If Not ci.OSFullName.Contains("Microsoft Windows 8") Then
            MessageBox.Show("The current OS is not supported. Run this program in a Windows 8 or Windows 8.1 PC.", "OS not supported", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End
        End If

        ' Scan for installed apps if the
        If Not AppSettings.ErrorDetected AndAlso AppSettings.ScanInstalledAppsAtStartup Then
            scanInstalledAppsButton_Click(sender, e)
        End If
    End Sub

    Private Async Sub scanInstalledAppsButton_Click(sender As Object, e As EventArgs) Handles scanInstalledAppsButton.Click, ScanForInstalledAppsToolStripMenuItem.Click
        ' Perform preparing operations
        ' Show the progress bar and reset its value
        If Not tSProgressBar.Visible Then
            tSProgressBar.Visible = True
        End If
        tSProgressBar.Value = 0

        ' Show and enable cancel button
        cancelLinkLabel.Visible = True
        cancelLinkLabel.Enabled = True

        ' Initialize the cancellation token source and retrieve the token
        cts = New CancellationTokenSource()
        Dim token As CancellationToken = cts.Token

        ' Clear the ListView groups, except the 'Custom' group
        ClearListViewGroups()

        ' Declare the root path: %LOCALAPPDATA%\Pacakges
        Dim rootFolder As New DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                            "\Packages")

        ' Set the progress bar maximum value, so we can track progress      
        tSProgressBar.Maximum = Await Task.Run(Function()
                                                   Return rootFolder.GetDirectories().Count()
                                               End Function)

        Try
            ' Process folders in the root path
            Await Task.Run(Async Function()
                               For Each folder As DirectoryInfo In rootFolder.GetDirectories()
                                   ' Throw the cancellation request if the token has one
                                   token.ThrowIfCancellationRequested()

                                   ' Set the ToolStripStatusLabel to the folder being processed
                                   tSStatusLabel.Text = "Analyzing: " & folder.FullName

                                   ' Create a new ListViewGroup which header and key are the folder's being processed name and
                                   ' add it to the ListView
                                   Dim folderGroup As New ListViewGroup(folder.Name, folder.Name)
                                   mainListView.Groups.Add(folderGroup)

                                   ' Add folder to the group
                                   Await ProcessFolders(folder, folderGroup, token)

                                   ' Increment progress bar value
                                   tSProgressBar.Increment(1)
                               Next
                           End Function, token)
        Catch oc As OperationCanceledException
        End Try

        ' Perform form cleanup operations
        ' Clear the cancellation token
        cts.Dispose()

        ' Enable or disable the 'Run Cleaner'
        ActivateButtons()

        ' Hide and disable cancel button
        cancelLinkLabel.Visible = False
        cancelLinkLabel.Enabled = False

        ' Reset the ToolStripStatusLabel text and hide the progress bar
        tSStatusLabel.Text = "Ready"
        If tSProgressBar.Visible Then
            tSProgressBar.Visible = False
        End If
    End Sub

    Private Async Sub addFolderButton_Click(sender As Object, e As EventArgs) Handles addFolderButton.Click, AddCustomFolderToolStripMenuItem.Click
        ' Create a new FolderBrowserDialog which will be used to choose the folder
        ' the user wants to add
        Using folderDialog As New FolderBrowserDialog() With {.Description = "Choose the folder you want to add", _
                                                              .ShowNewFolderButton = False}
            ' Process folder dialog
            If folderDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                ' Custom folders will be hold under the 'Custom' ListViewGroup
                ' Check if ListView contains it. If not, create it
                If mainListView.Groups("Custom") Is Nothing Then
                    mainListView.Groups.Add(New ListViewGroup("Custom", "Custom"))
                End If

                ' Create a new ListViewItem that will hold folder name and size
                Dim customItem As New ListViewItem(folderDialog.SelectedPath)
                customItem.Checked = True
                customItem.Group = mainListView.Groups("Custom")
                customItem.ToolTipText = customItem.Text

                ' Perform preparing operations to get the folder's size
                ' Initialize the cancellation token source and retrieve the token
                cts = New CancellationTokenSource()
                Dim token As CancellationToken = cts.Token

                ' Show and enable cancel button
                cancelLinkLabel.Visible = True
                cancelLinkLabel.Enabled = True

                ' Set ToolStripStatusLabel
                tSStatusLabel.Text = "Calculating size..."

                ' Show progress bar and set its properties
                If Not tSProgressBar.Visible Then
                    tSProgressBar.Visible = True
                End If
                tSProgressBar.Style = ProgressBarStyle.Marquee

                ' Asyncronously calculate folder's size
                Try
                    Await Task.Run(Async Function()
                                       customItem.SubItems.Add(Await GetFolderSize(folderDialog.SelectedPath, token))
                                   End Function)
                Catch oc As OperationCanceledException
                End Try

                ' And add it to the 'Custom' group and to the ListView
                mainListView.Items.Add(customItem)
            End If
        End Using

        ' Perform form cleanup operations
        ' Clear the cancellation token
        cts.Dispose()

        ' Hide and disable cancel button
        cancelLinkLabel.Visible = False
        cancelLinkLabel.Enabled = False

        ' Reset the ToolStripStatusLabel text and hide the progress bar
        tSStatusLabel.Text = "Ready"
        If tSProgressBar.Visible Then
            tSProgressBar.Visible = False
        End If
        tSProgressBar.Style = ProgressBarStyle.Blocks

        ' Enable or disable the 'Run Cleaner'
        ActivateButtons()
    End Sub

    Private Async Sub runCleanerButton_Click(sender As Object, e As EventArgs) Handles runCleanerButton.Click, RunCleanerToolStripMenuItem.Click
        ' TODO: pause token needs to be tested
        If runCleanerButton.Text = "Run Cleaner" Then
            runCleanerButton.Text = "Pause"

            ' If required prompts a confirm message before running the cleaner
            If Not AppSettings.ErrorDetected AndAlso AppSettings.ConfirmBeforeRunningCleaner Then
                If MessageBox.Show("Are you sure you want to clear the entire content of the selected folders?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) _
                    = Windows.Forms.DialogResult.Yes Then

                    Await RunCleaner()
                End If
            Else
                Await RunCleaner()
            End If
        ElseIf runCleanerButton.Text = "Pause" Then
            runCleanerButton.Text = "Resume"

            pts.IsPaused = True
        ElseIf runCleanerButton.Text = "Resume" Then
            runCleanerButton.Text = "Pause"

            pts.IsPaused = False
        End If
    End Sub

    Private Async Sub removeFolderButton_Click(sender As Object, e As EventArgs) Handles removeFolderButton.Click, RemoveFoldersToolStripMenuItem.Click
        ' If required prompts a confirm message before removing the selected folder
        If Not AppSettings.ErrorDetected AndAlso AppSettings.ConfirmWhenDeletingFolder Then
            If MessageBox.Show("Are you sure you want to remove " & mainListView.SelectedItems.Count & " from the list?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) _
                = Windows.Forms.DialogResult.Yes Then

                Await RemoveFolder()
            End If
        Else
            Await RemoveFolder()
        End If
    End Sub

    Private Sub mainListView_SelectedIndexChanged(sender As Object, e As EventArgs) Handles mainListView.SelectedIndexChanged
        ' Enable the "Remove" button when the selected items count is bigger than 0, otherwise disable it. 
        ' Also change the label of the button
        If mainListView.SelectedItems.Count = 0 Then
            removeFolderButton.Enabled = False
            removeFolderButton.Text = "Remove folder"
        ElseIf mainListView.SelectedItems.Count = 1 Then
            removeFolderButton.Enabled = True
            removeFolderButton.Text = "Remove folder"
        Else
            removeFolderButton.Enabled = True
            removeFolderButton.Text = "Remove folders"
        End If
    End Sub

    Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
        ' Exit the application
        Application.ExitThread()
    End Sub

    Private Async Sub OptionsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OptionsToolStripMenuItem.Click
        ' Check if the settings file exists. otherwise recreate it.
        If Not My.Computer.FileSystem.FileExists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Modern UI Apps Cleaner\config.dat") Then
            ' If the settings file doesn't exists, check if a backup exists.
            If My.Computer.FileSystem.FileExists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Modern UI Apps Cleaner\config.bak") Then
                My.Computer.FileSystem.CopyFile(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                               "\Modern UI Apps Cleaner\config.bak", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                               "\Modern UI Apps Cleaner\config.dat", True)
            Else
                ' If the backup doesn't exists, prompts the user to browse for a backup of the settings file
                If MessageBox.Show("Cannot find the settings file. Would you like browse for it?", "Restore settings", MessageBoxButtons.YesNo, MessageBoxIcon.Question) _
                    = Windows.Forms.DialogResult.Yes Then

                    ' Initialize a new OpenFileDialog to let the user browse for the settings file
                    Using openFile As New OpenFileDialog() With {.AddExtension = True, .AutoUpgradeEnabled = True, .CheckFileExists = True, .CheckPathExists = True, .DefaultExt = ".dat", _
                                                .DereferenceLinks = True, .Filter = "Configuration file (*.dat)|*.dat", .Multiselect = False, .Title = "Choose the configuration file"}

                        ' Process the file
                        ' If the user selected a valid file, then copy it to the settings folder and create a backup
                        If openFile.ShowDialog() = Windows.Forms.DialogResult.OK AndAlso Await CheckIfValidSettings() Then

                            Await Task.Run(Sub()
                                               My.Computer.FileSystem.CopyFile(openFile.FileName, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Modern UI Apps Cleaner\config.dat", True)

                                               My.Computer.FileSystem.CopyFile(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                           "\Modern UI Apps Cleaner\config.dat", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & _
                                                           "\Modern UI Apps Cleaner\config.bak", True)
                                           End Sub)
                        Else
                            ' If the file isn't valid or the user hasn't selected one, recreate the settings file.
                            Await CreateXMLSettingsFile()
                        End If
                    End Using
                    ' End OpenFileDialog
                Else
                    ' If the user doesn't want to browse for the settings file, recreate it.
                    Await CreateXMLSettingsFile()
                End If
            End If
        End If

        ' Initialize the options form and show it
        Using frmOptions As New optionsForm
            frmOptions.ShowDialog()
        End Using
    End Sub

    Private Sub openExplorerToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles openExplorerToolStripMenuItem.Click
        ' Create a new StringBuilder which will be used to hold the path of the folders that couldn't be opened
        Dim exceptionList As New StringBuilder

        For Each item As ListViewItem In mainListView.SelectedItems
            If item.Group IsNot mainListView.Groups("Custom") Then
                ' Process all groups except the "Custom" group
                Try
                    ' If the folder doesn't exist, throw an exception that will be catched and hadled at 'Catch ex As Exception'
                    If Not My.Computer.FileSystem.DirectoryExists( _
                        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & "\Packages\" & item.Group.Header & "\" & item.Text) Then

                        Throw New Exception
                    Else
                        Process.Start("explorer.exe", Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                        "\Packages\" & item.Group.Header & "\" & item.Text)
                    End If

                Catch ex As Exception
                    ' If the folder couldn't be opened, add its path to the exceptionList
                    If Not exceptionList.ToString().Contains(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                         "\Packages\" & item.Group.Header & "\" & item.Text) Then

                        exceptionList.AppendLine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) & _
                                         "\Packages\" & item.Group.Header & "\" & item.Text)
                    End If
                End Try
            Else
                ' Process the "Custom" group
                Try
                    ' If the folder doesn't exist, throw an exception that will be catched and hadled at 'Catch ex As Exception'
                    If Not My.Computer.FileSystem.DirectoryExists(item.Text) Then
                        Throw New Exception
                    Else
                        Process.Start("explorer.exe", item.Text)
                    End If

                Catch ex As Exception
                    ' If the folder couldn't be opened, add its path to the exceptionList
                    If Not exceptionList.ToString().Contains(item.Text) Then
                        exceptionList.AppendLine(item.Text)
                    End If
                End Try

            End If
        Next

        ' Show a MessageBox containing the files or folders that couldn't be deleted if there were any
        If exceptionList.ToString IsNot String.Empty Then
            MessageBox.Show("Some folders couldn't be opened: " + ControlChars.CrLf + exceptionList.ToString, _
                            "Modern UI Apps Cleaner", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        End If
    End Sub

    Private Sub AboutToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AboutToolStripMenuItem.Click
        ' Initialize and show the About window
        Using frmAbout As New frmAboutBox
            frmAbout.ShowDialog()
        End Using
    End Sub

    Private Sub cancelLinkLabel_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles cancelLinkLabel.LinkClicked
        ' Set the status label text to 'Cancelling'
        tSStatusLabel.Text = "Cancelling..."

        ' Throw the cancellation request
        If cts IsNot Nothing Then
            cts.Cancel()
        End If
    End Sub

    Private Async Sub RefreshFolderSizesToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles RefreshFoldersSizesToolStripMenuItem.Click
        ' Initialize the cancellation token source and retrieve the token
        cts = New CancellationTokenSource()
        Dim token As CancellationToken = cts.Token

        pts = New PauseTokenSource()
        Dim pauseToken As PauseToken = pts.Token

        ' Run the core task, passing the cancellation token
        Await RefreshFolderSizes(True, token, pauseToken)

        ' Clear the cancellation token
        cts.Dispose()
    End Sub

    Private Sub SelectAllToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SelectAllToolStripMenuItem.Click
        ' If every item is selected, deselect all; otherwise select all items    
        If mainListView.SelectedItems.Count = mainListView.Items.Count Then
            mainListView.SelectedItems.Clear()
            mainListView.Update()
        Else
            For Each item As ListViewItem In mainListView.Items
                item.Selected = True
            Next
        End If
    End Sub

    Private Sub UncheckSelectedFoldersToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles UncheckSelectedFoldersToolStripMenuItem.Click
        ' Uncheck selected folders
        For Each item As ListViewItem In mainListView.SelectedItems
            item.Checked = False
        Next
    End Sub

    Private Sub CheckSelectedFoldersToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CheckSelectedFoldersToolStripMenuItem.Click
        ' Check selected folders
        For Each item As ListViewItem In mainListView.SelectedItems
            item.Checked = True
        Next
    End Sub

    Private Sub mainContextMenuStrip_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles mainContextMenuStrip.Opening
        ' Set text an enabled properties for all the context menu items
        If mainListView.SelectedItems.Count = 0 Then
            RemoveFoldersToolStripMenuItem.Enabled = False
            RemoveFoldersToolStripMenuItem.Text = "Remove folder"
            UncheckSelectedFoldersToolStripMenuItem.Enabled = False
            CheckSelectedFoldersToolStripMenuItem.Enabled = False
            UncheckSelectedFoldersToolStripMenuItem.Text = "Uncheck selected folder"
            CheckSelectedFoldersToolStripMenuItem.Text = "Check selected folder"
            openExplorerToolStripMenuItem.Enabled = False
        ElseIf mainListView.SelectedItems.Count = 1 Then
            RemoveFoldersToolStripMenuItem.Enabled = True
            RemoveFoldersToolStripMenuItem.Text = "Remove folder"
            UncheckSelectedFoldersToolStripMenuItem.Text = "Uncheck selected folder"
            CheckSelectedFoldersToolStripMenuItem.Text = "Check selected folder"
            If mainListView.SelectedItems(0).Checked Then
                UncheckSelectedFoldersToolStripMenuItem.Enabled = True
                CheckSelectedFoldersToolStripMenuItem.Enabled = False
            Else
                UncheckSelectedFoldersToolStripMenuItem.Enabled = False
                CheckSelectedFoldersToolStripMenuItem.Enabled = True
            End If
            openExplorerToolStripMenuItem.Enabled = True
        Else
            RemoveFoldersToolStripMenuItem.Enabled = True
            RemoveFoldersToolStripMenuItem.Text = "Remove folders"
            UncheckSelectedFoldersToolStripMenuItem.Enabled = True
            CheckSelectedFoldersToolStripMenuItem.Enabled = True
            UncheckSelectedFoldersToolStripMenuItem.Text = "Uncheck selected folders"
            CheckSelectedFoldersToolStripMenuItem.Text = "Check selected folders"
            openExplorerToolStripMenuItem.Enabled = True
        End If

        ' Set the "Select All" ToolStripMenuItem text
        If mainListView.SelectedItems.Count = mainListView.Items.Count Then
            SelectAllToolStripMenuItem.Text = "Deselect all"
        ElseIf Not mainListView.Items.Count = 0 Then
            SelectAllToolStripMenuItem.Text = "Select all"
        End If
    End Sub

    Private Async Sub CheckForUpdatesToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CheckForUpdatesToolStripMenuItem.Click
        Dim info As Deployment.Application.UpdateCheckInfo = Nothing

        If (Deployment.Application.ApplicationDeployment.IsNetworkDeployed) Then
            Dim AD As Deployment.Application.ApplicationDeployment = Deployment.Application.ApplicationDeployment.CurrentDeployment

            Try
                info = Await Task.Run(Function()
                                          Return AD.CheckForDetailedUpdate()
                                      End Function)
            Catch dde As Deployment.Application.DeploymentDownloadException
                MessageBox.Show("The new version of the application cannot be downloaded at this time. " + ControlChars.Lf & ControlChars.Lf & "Please check your network connection, or try again later. Error: " + dde.Message)
                Return
            Catch ioe As InvalidOperationException
                MessageBox.Show("This application cannot be updated. It is likely not a ClickOnce application. Error: " & ioe.Message)
                Return
            End Try

            If (info.UpdateAvailable) Then
                Dim doUpdate As Boolean = True

                If (Not info.IsUpdateRequired) Then
                    Dim dr As DialogResult = MessageBox.Show("An update is available. Would you like to update the application now?", "Update Available", MessageBoxButtons.OKCancel)
                    If (Not System.Windows.Forms.DialogResult.OK = dr) Then
                        doUpdate = False
                    End If
                Else
                    ' Display a message that the app MUST reboot. Display the minimum required version.
                    MessageBox.Show("This application has detected a mandatory update from your current " & _
                        "version to version " & info.MinimumRequiredVersion.ToString() & _
                        ". The application will now install the update and restart.", _
                        "Update Available", MessageBoxButtons.OK, _
                        MessageBoxIcon.Information)
                End If

                If (doUpdate) Then
                    Try
                        AD.UpdateAsync()
                        MessageBox.Show("The application has been upgraded, and will now restart.")
                        Application.Restart()
                    Catch dde As Deployment.Application.DeploymentDownloadException
                        MessageBox.Show("Cannot install the latest version of the application. " & ControlChars.Lf & ControlChars.Lf & "Please check your network connection, or try again later.")
                        Return
                    End Try
                End If
            Else
                MessageBox.Show("You already have the lastest version.", "Check for updates", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End If
        End If
    End Sub
End Class
